#include "mifare_card.h"
#include "ic_des.h"
#include "psam_card.h"


/**
  * 功能: M1卡验证权限
  * 
  *
  * 返回值:
  * 	   
  **/

s32 mifare_card_check_key(reader_op *reader, u8 block, u8 key_type)
{
	s32 ret;
	card_data send;

	if (!reader) {
		debug("mifare_check_key: pare error!!!\n");
		return RET_ERR;
	}

	memset(send.data, 0, READER_BUF_SIZ);
	memcpy(send.data, reader->key_data, reader->key_len);

	/* 验证密钥 */
	send.type    		= READER_CONTACTLESS_M1;
	send.cla	 		= 0x00;
	send.cmd.mf_comm	= RC500_AUTHENTICATION;
	send.pa1.mf_flag	= key_type; 
	send.pa2.mf_sector	= block;
	send.len.mf_len		= reader->key_len; 

	ret = reader_communication(reader, &send);
	
	return ret;
}


/**
  * 功能: M1卡读块操作
  * 
  *
  * 返回值:
  * 	   
  **/

s32 mifare_card_read_block(reader_op *reader, card_data *send, u8 block)
{
	s32 ret;
	
	if (!reader || !send) {
		debug("mifare_card_read_block: para error!!!\n");
		return RET_ERR;
	}
	
	/* 读取块数据 */
	memset(send->data, 0, READER_BUF_SIZ);
	send->type    		= READER_CONTACTLESS_M1;
	send->cla	 		= 0x00;
	send->cmd.mf_comm	= RC500_READ_CARD;
	send->pa1.mf_flag	= 0x00; 
	send->pa2.mf_sector	= block;
	send->len.mf_len	= 0x00; 

	ret = reader_communication(reader, send);
	if (ret) {
		debug("mifare_card_read_block failed!!! errno: [%02x%02x]\n", \
			send->sw1, send->sw2);
		return RET_ERR;
	}
	else {
		return send->len.mf_len;
	}
}


/**
  * 功能: M1卡获取TAC值
  * 
  *
  * 返回值:
  * 	   
  **/

static int mifare_card_get_tac(reader_op *reader, mifare_data *deal_data)
{
	s32 ret = 0;
	card_data send;

	memcpy(send.data, reader->card_num, 8); // 分散因子 
	/* PSAM通用DES初始化-获得子密钥 */
	send.type    = READER_CONTACT_SAM1;
	send.cla	 = 0x80;
	send.cmd.ins = APDU_INIT_FOR_DESCRYPT;
	send.pa1.p1  = CTCC_YJD_KEY_FLAG_TAC; 
	send.pa2.p2  = CTCC_YJD_KEY_ID;  
	send.len.lc  = 0x08; 
	send.le      = 0x00; 

	ret = reader_communication(reader, &send);
	if (((send.sw1 << 8) | send.sw2) != 0x9000) {
		debug("mifare_card_get_tac no.1 failed!!! errno: [%02x%02x]\n", \
			send.sw1, send.sw2);

		return ((send.sw1 << 8) | send.sw2);
	}

	memset(send.data, 0, READER_BUF_SIZ);
	send.data[0]  = 0x01;
	send.data[1]  = 0x08;
	send.data[2]  = reader->terminal[0];
	send.data[3]  = reader->terminal[1];
	send.data[4]  = reader->terminal[2];
	send.data[5]  = reader->terminal[3];
	send.data[6]  = reader->terminal[4];
	send.data[7]  = reader->terminal[5];
	send.data[8]  = deal_data->in.deal_index[0];
	send.data[9]  = deal_data->in.deal_index[1];
	send.data[10] = deal_data->in.deal_index[2];
	send.data[11] = deal_data->in.deal_index[3];
	send.data[12] = 0x00;
	send.data[13] = 0x01;
	send.data[14] = 0x00;
	send.data[15] = 0x00;
	send.data[16] = 0x00;
	send.data[17] = 0x00;
	send.data[18] = 0x00;
	send.data[19] = 0x00;
	send.data[20] = deal_data->in.deal_residue[0];
	send.data[21] = deal_data->in.deal_residue[1];
	send.data[22] = deal_data->in.deal_residue[2];
	send.data[23] = deal_data->in.deal_residue[3];
	send.data[24] = deal_data->in.deal_val[0];
	send.data[25] = deal_data->in.deal_val[1];
	send.data[26] = deal_data->in.deal_val[2];
	send.data[27] = deal_data->in.deal_val[3];
	send.data[28] = deal_data->in.deal_time[0];
	send.data[29] = deal_data->in.deal_time[1];
	send.data[30] = deal_data->in.deal_time[2];
	send.data[31] = deal_data->in.deal_time[3];
	send.data[32] = deal_data->in.deal_time[4]; 
	send.data[33] = deal_data->in.deal_time[5]; 
	send.data[34] = deal_data->in.deal_time[6];
	send.data[35] = 0x00;
	send.data[36] = 0x00;
	send.data[37] = deal_data->out.deal_cnt[0];
	send.data[38] = deal_data->out.deal_cnt[1];
	send.data[39] = 0x80;

	
	/* PSAM DES计算-获得过程密钥 */
	send.type    = READER_CONTACT_SAM1;
	send.cla	 = 0x80;
	send.cmd.ins = APDU_DES_CRYPT;
	send.pa1.p1  = 0x05; 
	send.pa2.p2  = 0x00; 
	send.len.lc  = 40; 
	send.le      = 0x00; 

	ret = reader_communication(reader, &send);
	if (send.sw1 == 0x61) {
		ret = psam_apdu_get_response(reader, &send, send.sw2);
		if (ret) {
			return RET_ERR;
		}
	}

	// 获得TAC值
	deal_data->out.deal_tac[0] = send.data[0];
	deal_data->out.deal_tac[1] = send.data[1];
	deal_data->out.deal_tac[2] = send.data[2];
	deal_data->out.deal_tac[3] = send.data[3];

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_deal: get tac success: tac_val[%02X%02X%02X%02X]\n", \
			deal_data->out.deal_tac[0], deal_data->out.deal_tac[1], \
			deal_data->out.deal_tac[2], deal_data->out.deal_tac[3]);
	}
	
	return RET_OK;
}


/**
  * 功能: M1写块
  * 
  *
  * 返回值:
  * 	   
  **/

static s32 mifare_card_write(reader_op *reader, u8 block, u8 *block_data, u8 len)
{
	s32 ret = 0;
	card_data send;

	if (!block_data) {
		debug("mifare_card_write: para error!!!\n");
		return RET_ERR;
	}
	
	memcpy(send.data, block_data, len);
	send.type    		= READER_CONTACTLESS_M1;
	send.cla	 		= 0x00;
	send.cmd.mf_comm	= RC500_WRITE_CARD;
	send.pa1.mf_flag	= 0x00; 
	send.pa2.mf_sector	= block;
	send.len.mf_len		= len; 

	ret = reader_communication(reader, &send);
	if (ret) {
		debug("mifare_card_write: write block failed!!! errno: [%02x%02x]\n", \
			send.sw1, send.sw2);
		return RET_ERR;
	}

	return RET_OK;
}


/**
  * 功能: M1卡消费交易流程
  * 
  *
  * 返回值:
  * 	   
  **/

s32 mifare_card_cons(void *op, void *data)
{
	u8 block_data[16] = {0, 0, 0};
	u8 idx = 0;
	u16 deal_cnt = 0; // 交易次数
	reader_op *reader = (reader_op *)op;
	mifare_data *deal_data = (mifare_data *)data;
	s32 ret = 0;
	u32 deal_val = 0;
	u32 discount_val = 0; 
	u32 money_val = 0;
	u32 money_val_data[4] = {0, 0, 0};
	card_data send;


	if (!op ||  NORMAL_M1_CARD != reader->card_type) {
		debug("mifare_card_cons: pare error!!!\n");
		return RET_ERR;
	}

	deal_data->out.deal_ret = DEAL_RESULT_FAIL;
	ret = reader_get_factor(reader);
	if (ret) {
		return RET_ERR;
	}

	ret = psam_card_get_key(reader, CTCC_YJD_KEY_FLAG, CTCC_YJD_KEY_ID); // 获取key密钥
	if (ret) {
		return RET_ERR;
	}

	/* 终端交易序号-取记录的数据库序号 */
	deal_data->in.deal_index[0] = reader->index[0];
	deal_data->in.deal_index[1] = reader->index[1];
	deal_data->in.deal_index[2] = reader->index[2];
	deal_data->in.deal_index[3] = reader->index[3];

	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_read_block(reader, &send, S8B0);
	if (ret <= 0) {
		return RET_ERR;
	}
	else {
		if (ret > sizeof(block_data)) {
			memcpy(block_data, send.data, 16);
		}
		else {
			memcpy(block_data, send.data, ret);
		}
	}


	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: read [S8B0] block data success\n");
	}

	if (deal_data->in.deal_type == 0x01) {
		deal_cnt = (block_data[1] << 8) | block_data[2];
		deal_cnt++;
		block_data[1] = deal_cnt >> 8; // 高8位
		block_data[2] = deal_cnt & 0xFF;
	}
	else {
		deal_cnt = (block_data[7] << 8) | block_data[8];
		deal_cnt++;
		block_data[7] = deal_cnt >> 8; // 高8位
		block_data[8] = deal_cnt & 0xFF;
	}

	deal_data->out.deal_cnt[0] = deal_cnt >> 8;
	deal_data->out.deal_cnt[1] = deal_cnt & 0xFF;
	ret = mifare_card_get_tac(reader, deal_data); //未验证
	if (ret) {
		return RET_ERR;
	}

	memset(send.data, 0, READER_BUF_SIZ);
	send.data[0]  = deal_data->out.deal_cnt[0];
	send.data[1]  = deal_data->out.deal_cnt[1];
	send.data[2]  = deal_data->in.deal_val[0];
	send.data[3]  = deal_data->in.deal_val[1];
	send.data[4]  = deal_data->in.deal_val[2];
	send.data[5]  = deal_data->in.deal_val[3];
	send.data[6]  = deal_data->in.deal_type;	
	send.data[7]  = reader->terminal[0];
	send.data[8]  = reader->terminal[1];
	send.data[9]  = reader->terminal[2];
	send.data[10] = reader->terminal[3];
	send.data[11] = deal_data->in.deal_time[0];
	send.data[12] = deal_data->in.deal_time[1];
	send.data[13] = deal_data->in.deal_time[2];
	send.data[14] = deal_data->in.deal_time[3];
	send.data[15] = cel_crc(send.data, 15);

	switch (block_data[0]) { // 确定扇区首块地址(环形记录块 共9条记录)
		case 1:
		case 2:
		case 3:
			idx = S2B0;
			break;
			
		case 4:
		case 5:
		case 6:
			idx = S3B0;
			break;
			
		case 7:
		case 8:
		case 9:
			idx = S4B0;
			break;
			
		default:
			block_data[0] = 1;
			idx = S2B0;
			break;
	}

	ret = mifare_card_check_key(reader, idx+3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	idx +=  (block_data[0]-1)%3; // 确定块
	ret = mifare_card_write(reader, idx, send.data, 16);
	if (ret) {
		return RET_ERR;
	}
	
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: write [%02d] block success\n", idx);
	}

	block_data[0] = idx + 1;
	if (deal_data->in.deal_type == 0x01) {
		block_data[5] = 0x01; // 钱包开始
	}
	else {
		block_data[5] = 0x03; // 补贴钱包开始
	}

	block_data[15] = cel_crc(block_data, 15);

	// 写交易配置与控制信息
	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B0, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B1, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: write [S8B0 S8B1] block success\n");
	}

	// 写入钱包数据
	deal_val = ((deal_data->in.deal_val[0] << 24) | \
		(deal_data->in.deal_val[1] << 16) | \
		(deal_data->in.deal_val[2] << 8) | \
		(deal_data->in.deal_val[3]));
	discount_val = ((deal_data->in.deal_rebate[0] << 24) | \
		(deal_data->in.deal_rebate[1] << 16) | \
		(deal_data->in.deal_rebate[2] << 8) | \
		(deal_data->in.deal_rebate[3]));
	money_val = ((deal_data->in.deal_residue[0] << 24) | \
		(deal_data->in.deal_residue[1] << 16) | \
		(deal_data->in.deal_residue[2] << 8) | \
		(deal_data->in.deal_residue[3]));

	deal_val -= discount_val;
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: deal residue no.1@ [%x]\n", money_val);
	}

	if (money_val < deal_val) {
		debug("mifare_card_cons: deal residue less\n");
		deal_data->out.deal_ret = DEAL_RESULT_MONEY_LESS;
		return RET_ERR;
	}
	else {
		money_val -= deal_val;
	}

	if (platform.endian == APP_BIG_ENDIAN) {
		money_val_data[0] = (((money_val >> 24) & 0xFF) | \
			(((money_val >> 8)  & 0xFF00) | \
			((money_val << 8)  & 0xFF0000) | \
			((money_val << 24) & 0xFF000000)));
	}
	else {
		money_val_data[0] = money_val;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: deal residue no.2@ [%x]\n", money_val_data[0]);
	}

	money_val_data[1] = ~money_val_data[0];
	money_val_data[2] = money_val_data[0];
	money_val_data[3] = 0xFF00FF00;

	if (deal_data->in.deal_type == 0x01) {
		idx = S1B0;
	}
	else {
		idx = S5B0;
	}

	ret = mifare_card_check_key(reader, idx+3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, idx, (u8 *)money_val_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, idx+1, (u8 *)money_val_data, 16);
	if (ret) {
		return RET_ERR;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: write [%02d %02d] block success\n", idx, idx+1);
	}

	// 写入配置信息
	if (deal_data->in.deal_type == 0x01) {
		block_data[5] = 0x02;
	}
	else {
		block_data[5] = 0x04;
	}
	
	block_data[15] = cel_crc(block_data, 15);

	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B0, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B1, block_data, 16);
	if (ret) {
		return RET_ERR;
	}
	
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_cons: write [S8B0 S8B1] block success\n");
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
		debug("mifare_card_cons: cons done\n");
	}
	
	deal_data->out.deal_ret = DEAL_RESULT_NORMAL;
	return RET_OK;
}

 

/**
  * 功能: m1卡圈存交易流程
  * 
  *
  * 返回值:
  * 	   
  **/

s32 mifare_card_load(void *op, void *data)
{
	u8 block_data[16] = {0, 0, 0};
	u8 idx = 0;
	u16 deal_cnt = 0; // 交易次数
	reader_op *reader = (reader_op *)op;
	mifare_data *deal_data = (mifare_data *)data;
	s32 ret = 0;
	u32 deal_val = 0;
	u32 discount_val = 0; 
	u32 money_val = 0;
	u32 money_val_data[4] = {0, 0, 0};
	card_data send;


	if (!op ||  NORMAL_M1_CARD != reader->card_type) {
		debug("mifare_card_load: pare error!!!\n");
		return RET_ERR;
	}

	deal_data->out.deal_ret = DEAL_RESULT_FAIL;
	ret = reader_get_factor(reader);
	if (ret) {
		return RET_ERR;
	}

	ret = psam_card_get_key(reader, CTCC_YJD_KEY_FLAG, CTCC_YJD_KEY_ID); // 获取key密钥
	if (ret) {
		return RET_ERR;
	}

	/* 终端交易序号-取记录的数据库序号 */
	deal_data->in.deal_index[0] = reader->index[0];
	deal_data->in.deal_index[1] = reader->index[1];
	deal_data->in.deal_index[2] = reader->index[2];
	deal_data->in.deal_index[3] = reader->index[3];

	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_read_block(reader, &send, S8B0);
	if (ret <= 0) {
		return RET_ERR;
	}
	else {
		if (ret > sizeof(block_data)) {
			memcpy(block_data, send.data, 16);
		}
		else {
			memcpy(block_data, send.data, ret);
		}
	}


	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: read [S8B0] block data success\n");
	}

	if (deal_data->in.deal_type == 0x01) {
		deal_cnt = (block_data[1] << 8) | block_data[2];
		deal_cnt++;
		block_data[1] = deal_cnt >> 8; // 高8位
		block_data[2] = deal_cnt & 0xFF;
	}
	else {
		deal_cnt = (block_data[7] << 8) | block_data[8];
		deal_cnt++;
		block_data[7] = deal_cnt >> 8; // 高8位
		block_data[8] = deal_cnt & 0xFF;
	}

	deal_data->out.deal_cnt[0] = deal_cnt >> 8;
	deal_data->out.deal_cnt[1] = deal_cnt & 0xFF;
	ret = mifare_card_get_tac(reader, deal_data);
	if (ret) {
		return RET_ERR;
	}

	memset(send.data, 0, READER_BUF_SIZ);
	send.data[0]  = deal_data->out.deal_cnt[0];
	send.data[1]  = deal_data->out.deal_cnt[1];
	send.data[2]  = deal_data->in.deal_val[0];
	send.data[3]  = deal_data->in.deal_val[1];
	send.data[4]  = deal_data->in.deal_val[2];
	send.data[5]  = deal_data->in.deal_val[3];
	send.data[6]  = deal_data->in.deal_type;	
	send.data[7]  = reader->terminal[0];
	send.data[8]  = reader->terminal[1];
	send.data[9]  = reader->terminal[2];
	send.data[10] = reader->terminal[3];
	send.data[11] = deal_data->in.deal_time[0];
	send.data[12] = deal_data->in.deal_time[1];
	send.data[13] = deal_data->in.deal_time[2];
	send.data[14] = deal_data->in.deal_time[3];
	send.data[15] = cel_crc(send.data, 15);

	switch (block_data[0]) { // 确定扇区首块地址(环形记录块 共9条记录)
		case 1:
		case 2:
		case 3:
			idx = S2B0;
			break;
			
		case 4:
		case 5:
		case 6:
			idx = S3B0;
			break;
			
		case 7:
		case 8:
		case 9:
			idx = S4B0;
			break;
			
		default:
			block_data[0] = 1;
			idx = S2B0;
			break;
	}

	ret = mifare_card_check_key(reader, idx+3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	idx +=  (block_data[0]-1)%3; // 确定块
	ret = mifare_card_write(reader, idx, send.data, 16);
	if (ret) {
		return RET_ERR;
	}
	
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: write [%02d] block success\n", idx);
	}

	block_data[0] = idx + 1;
	if (deal_data->in.deal_type == 0x01) {
		block_data[5] = 0x01; // 钱包开始
	}
	else {
		block_data[5] = 0x03; // 补贴钱包开始
	}

	block_data[15] = cel_crc(block_data, 15);

	// 写交易配置与控制信息
	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B0, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B1, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: write [S8B0 S8B1] block success\n");
	}

	// 写入钱包数据
	deal_val = ((deal_data->in.deal_val[0] << 24) | \
		(deal_data->in.deal_val[1] << 16) | \
		(deal_data->in.deal_val[2] << 8) | \
		(deal_data->in.deal_val[3]));
	discount_val = ((deal_data->in.deal_rebate[0] << 24) | \
		(deal_data->in.deal_rebate[1] << 16) | \
		(deal_data->in.deal_rebate[2] << 8) | \
		(deal_data->in.deal_rebate[3]));
	money_val = ((deal_data->in.deal_residue[0] << 24) | \
		(deal_data->in.deal_residue[1] << 16) | \
		(deal_data->in.deal_residue[2] << 8) | \
		(deal_data->in.deal_residue[3]));

	deal_val += discount_val;
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: deal residue no.1@ [%x]\n", money_val);
	}

	money_val += deal_val;

	if (platform.endian == APP_BIG_ENDIAN) {
		money_val_data[0] = (((money_val >> 24) & 0xFF) | \
			(((money_val >> 8)  & 0xFF00) | \
			((money_val << 8)  & 0xFF0000) | \
			((money_val << 24) & 0xFF000000)));
	}
	else {
		money_val_data[0] = money_val;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: deal residue no.2@ [%x]\n", money_val_data[0]);
	}

	money_val_data[1] = ~money_val_data[0];
	money_val_data[2] = money_val_data[0];
	money_val_data[3] = 0xFF00FF00;

	if (deal_data->in.deal_type == 0x01) {
		idx = S1B0;
	}
	else {
		idx = S5B0;
	}

	ret = mifare_card_check_key(reader, idx+3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, idx, (u8 *)money_val_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, idx+1, (u8 *)money_val_data, 16);
	if (ret) {
		return RET_ERR;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: write [%02d %02d] block success\n", idx, idx+1);
	}

	// 写入配置信息
	if (deal_data->in.deal_type == 0x01) {
		block_data[5] = 0x02;
	}
	else {
		block_data[5] = 0x04;
	}
	
	block_data[15] = cel_crc(block_data, 15);

	ret = mifare_card_check_key(reader, S8B3, MIFARE_KB);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B0, block_data, 16);
	if (ret) {
		return RET_ERR;
	}

	ret = mifare_card_write(reader, S8B1, block_data, 16);
	if (ret) {
		return RET_ERR;
	}
	
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mifare_card_load: write [S8B0 S8B1] block success\n");
	}


	if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
		debug("mifare_card_load: load done\n");
	}

	deal_data->out.deal_ret = DEAL_RESULT_NORMAL;
	return RET_OK;
}


